/*
 * Copyright (c) Ulrich Hilger, http://dev.uhilger.de, all rights reserved.
 *
 * Published under the terms and conditions of the Apache License 2.0,
 * see http://www.apache.org/licenses/LICENSE-2.0
 */

package de.uhilger.servicehub.model;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

/**
 *
 * @author Ulrich Hilger, <a href="http://dev.uhilger.de" target="_blank">http://dev.uhilger.de</a>
 * @author Published under the terms and conditions of
 * the <a href="http://www.apache.org/licenses/LICENSE-2.0" target="_blank">Apache License 2.0</a>
 */
public class ServletContainerFactory {

  public ServletContainerFactory() {
    super();
    //System.out.println("Factory classpath at construct" + System.getProperty("java.class.path"));
  }
  
  /**
   * Register a ServletContainer with this ServletContainerFactory
   * @param libDir  the absolute path and name of the directory that
   * has the servlet container binaries to register with this factory
   * @see de.uhilger.servicehub.model.ServletContainerFactory#createServletContainer(java.lang.String)
   */
  public static void registerServletContainer(String libDir) throws IOException {
    File[] files = new File(libDir).listFiles();
    for(int i = 0; i < files.length; i++) {
      if(files[i].getName().endsWith(".jar")) {
        //System.out.println("Factory adds " + files[i]);
        addFile(files[i]);
      } else if(files[i].isDirectory()) {
        registerServletContainer(files[i].getAbsolutePath());
      }
    }
  }

  /**
   * Create a new ServletContainer
   * @param className  name of class to create the new container from
   * @return  the newly created instance of a ServletContainer
   */
  public static ServletContainer createServletContainer(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    //System.out.println("Factory classpath at before construction of class " + className +
    //  ": " + System.getProperty("java.class.path"));
    return (ServletContainer) Class.forName(className).newInstance();
  }

  /* --------------------------------------------------------------------------------------- */

  /*
   * Dynamic class loading facility as found at
   * http://forums.sun.com/thread.jspa?threadID=300557&start=15
   */

  // The methods addFile and associated final Class[] parameters were gratefully copied from
  // anthony_miguel @ http://forum.java.sun.com/thread.jsp?forum=32&thread=300557&tstart=0&trange=15
  private static final Class[] parameters = new Class[]{URL.class};

  public static void addFile(String s) throws IOException {
    File f = new File(s);
    addFile(f);
  }

  public static void addFile(File f) throws IOException {
    addURL(f.toURL());
  }

  public static void addURL(URL u) throws IOException {
    URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class sysclass = URLClassLoader.class;
    try {
      Method method = sysclass.getDeclaredMethod("addURL", parameters);
      method.setAccessible(true);
      method.invoke(sysloader, new Object[]{u});
    } catch (Throwable t) {
      t.printStackTrace();
      throw new IOException("Error, could not add URL to system classloader");
    }
  }
}
